package com.doctor.fss.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.doctor.fss.model.TicketResp;
import com.doctor.fss.util.OkHttpUtil;
import okhttp3.MediaType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@RestController
public class SignController {
    private static final Logger logger = LoggerFactory.getLogger(SignController.class);
    public static final MediaType mediaType = MediaType.parse("application/json");

    @Value("${ticket.url}")
    private String ticketUrl;

    @Value("${user.url}")
    private String userUrl;

    @Value("${jstickets.url}")
    private String jstickets;

    @Value("${client.id}")
    private String clientId;

    @Value("${client.secret}")
    private String clientSecret;

    /**
     * 鉴权
     * @param req
     * @return
     */
    @RequestMapping(value = "/getSignature", method = RequestMethod.POST)
    public Map getSignature(HttpServletRequest req) {
        //Step1:获取access token
        //根据client_id,client_secret和已经获取的免登code等参数获取access_token信息
        TicketResp ticketResp  ;
        String accessToken="";

        //获取access token相关参数列表
        String typeParamValue = "u";
        String clientIdParamValue =clientId ;
        String clientSecretParamValue = clientSecret;
        if (clientId == null || clientId.equals("")) {
            System.out.println("请根据README.md文档配置client_id和client_secret");
            System.exit(1);
        }
        String stateValue = "1";
        Map<String, String> ticketBodyParams = new HashMap<>();
        ticketBodyParams.put("client_id", clientIdParamValue);
        ticketBodyParams.put("client_secret", clientSecretParamValue);

        //转换相关参数列表为Json格式
        String ticketBody = JSONObject.toJSONString(ticketBodyParams);

        try {
            //发送post请求并获取access token相关信息
            String ticketResult = OkHttpUtil.post(ticketUrl, ticketBody, mediaType);
            ticketResp = JSON.parseObject(ticketResult, TicketResp.class);
            // 请务必根据接口过期时间缓存AccessToken，避免重复获取
            accessToken = ticketResp!=null?ticketResp.getAccess_token():null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        //Step2:获取jsapi_ticket
        //通过access token获取jsapi_ticket
        Map<String, String> userHeaderParams = new HashMap<>();
        userHeaderParams.put("x-wlk-Authorization", accessToken);
        Map<String, String> urlParams = new HashMap<>();
        TicketResp jsapiResult;
        try{
            //携带access token发送get请求并获取免登用户的userId信息
            String jsapi = OkHttpUtil.get(jstickets, userHeaderParams, urlParams);
            System.out.println("jsapiResult response: " + jsapi);
            System.out.println("accessToken: " + accessToken);
            jsapiResult = JSON.parseObject(jsapi, TicketResp.class);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return null;
        }

        //Step3:签名信息生成 signature
        String nonce_str= get_nonce_str();
        long timestamp= create_timestamp();
        String  signature = "";
        //获取当前网页URL
        try {
            signature = sign(jsapiResult.getJstickets(),nonce_str,timestamp,"http://gieibr.natappfree.cc/index");
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String,String> map = new HashMap<String,String>();
        map.put("appId",clientId);
        map.put("timeStamp",Long.toString(timestamp));
        map.put("nonceStr",nonce_str);
        map.put("signature",signature);
        System.out.println("appId: " + clientId);
        System.out.println("timeStamp: " + Long.toString(timestamp));
        System.out.println("nonceStr: " + nonce_str);
        System.out.println("signature: " + signature);
        return  map;
    }

    private static String bytesToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    public static String sign(String jsticket, String nonceStr, long timeStamp, String url) throws Exception {
        String urldecode = null;
        try {
            urldecode = java.net.URLDecoder.decode(url, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String plain = "jsapi_ticket=" + jsticket + "&noncestr=" + nonceStr + "&timestamp=" + String.valueOf(timeStamp)
                + "&url=" + urldecode;
        try {
            MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
            sha256.reset();
            sha256.update(plain.getBytes("UTF-8"));
            return bytesToHex(sha256.digest());
        } catch (NoSuchAlgorithmException e) {
            throw new Exception(e.getMessage());
        } catch (UnsupportedEncodingException e) {
            throw new Exception(e.getMessage());
        }
    }
    //生成随机字符串nonce_str
    public static String get_nonce_str() {
        return UUID.randomUUID().toString();
    }
    private static long create_timestamp(){
        return System.currentTimeMillis()/1000;
    }
}
